<template>
  <el-form ref="formRef" :rules="rules" :model="modelValue">
    <el-row>
      <el-col :span="item.span || 24" :key="item.key" v-for="item in formItems">
        <el-form-item :prop="item.key" :label="item.label">
          <slot :value="modelValue[item.key]" :name="item.key">
            <component
              :is="getComponent(item)"
              v-bind="getProps(item)"
              v-model="modelValue[item.key]"
            ></component>
          </slot>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
import { ElInput, ElInputNumber, ElSelect, FormInstance } from "element-plus"
import { FormItems, IFormItem } from "@/types/lowCodeForm.type"
import { ref } from "vue"

interface IProps {
  formItems: FormItems
  rules: Record<string, any>
}
defineProps<IProps>()

const modelValue = defineModel<Record<string, any>>({ required: true })

const formRef = ref<FormInstance | null>(null)

defineExpose({
  validate: (...args: Parameters<NonNullable<FormInstance>["validate"]>) => {
    if (formRef.value && formRef.value.validate) {
      return formRef.value.validate(...args)
    }
    return Promise.reject(new Error("formRef 未初始化"))
  }
})

// 组件映射
const componentMap: Record<string, any> = {
  input: ElInput,
  number: ElInputNumber,
  select: ElSelect
}

function getComponent(item: IFormItem) {
  const { type } = item
  if (typeof type !== "string") return type()
  return componentMap[(type as keyof typeof componentMap) || "input"]
}

function getProps(item: IFormItem) {
  const result = { ...item.props }
  // 排除不需要的属性
  const excludeKeys = ['label', 'key', 'type', 'span', 'hidden', 'props']
  for (let key in item) {
    if (!excludeKeys.includes(key)) {
      result[key] = item[key]
    }
  }
  return result
}
</script>
